package com.fjec.market.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjec.common.enums.EnumSysCode;
import com.fjec.common.protocol.JsonResult;
import com.fjec.common.shiro.AccountInfo;
import com.fjec.common.util.DateUtil;
import com.fjec.common.util.SequenceIdGenerator;
import com.fjec.common.ys.YsProperties;
import com.fjec.market.entity.*;
import com.fjec.market.mapper.BizServOrderMapper;
import com.fjec.market.mapper.BizSubServOrderMapper;
import com.fjec.market.mapper.InfoServiceProjectMapper;
import com.fjec.market.rabbitmq.provider.PreparePayProvider;
import com.fjec.market.service.*;
import com.fjec.market.view.ServOrderItem;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 044.服务订单表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2020-09-21
 */
@Service
public class BizServOrderServiceImpl extends ServiceImpl<BizServOrderMapper, BizServOrder> implements IBizServOrderService {

    @Resource
    private BizServOrderMapper mapper;

    @Resource
    private BizSubServOrderMapper subServOrderMapper;

    @Resource
    private IBizSubServOrderService bizSubServOrderService;

    @Resource
    private SequenceIdGenerator idGenerator;

    @Resource
    private InfoServiceProjectMapper serviceProjectMapper;

    @Resource
    private IBizDepositOperateRecordService bizDepositOperateRecordService;

    @Autowired
    private YsProperties ysProperties;

    @Autowired
    private PreparePayProvider preparePayProvider;

    @Resource
    private IInfoYsepayRegisterService infoYsepayRegisterService;

    @Resource
    private IInfoServiceProjectService infoServiceProjectService;

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Long saveOrder(Integer totalPrice, Integer orderType, List<ServOrderItem> productList, String subOpenId, Long userId) {
        // 获取服务Id列表
        List<Long> servIdList = productList.stream().map(ServOrderItem::getServId).collect(Collectors.toList());

        List<InfoServiceProject> servEntityList = serviceProjectMapper.selectBatchIds(servIdList);
        // 生成主订单Id
        LocalDateTime now = DateUtil.nowLdt();
        Long orderId = idGenerator.nextId();
        BizServOrder order = new BizServOrder();
        order.setId(orderId);
        order.setUserId(userId);
        order.setRealAmount(0);
        order.setUseDisc(0);
        order.setOrderType(orderType);
        order.setOrderStatus(1);
        order.setDelFlag(0);
        order.setCreateTime(now);
        // 循环保存子订单
        Integer orderRealAmount = 0;
        for (InfoServiceProject servEntity : servEntityList) {
            BizSubServOrder subOrder = new BizSubServOrder();
            subOrder.setServId(servEntity.getId());
            subOrder.setOrderId(orderId);

            subOrder.setUseDisc(0);
            subOrder.setDelFlag(0);
            subOrder.setDetailStatus(0); // 正常状态
            subOrder.setOrderStatus(1); // 未付款
            subOrder.setCreateTime(now);
            // 保存快照
            Map<String, Object> snapshotMap = new HashMap<>();
            snapshotMap.put("servType", servEntity.getServType());
            snapshotMap.put("servName", servEntity.getServName());
            snapshotMap.put("limitNum", servEntity.getLimitNum());
            snapshotMap.put("servDesc", servEntity.getServDesc());
            snapshotMap.put("vaild", servEntity.getVaild());
            snapshotMap.put("cashExchanged", servEntity.getCashExchanged());
            snapshotMap.put("servPic", servEntity.getServPic());
            snapshotMap.put("amount", servEntity.getAmount());
            subOrder.setServSnapshot(snapshotMap);
            // 根据数量计算价格
            for (ServOrderItem item : productList) {
                if (item.getServId() != null && servEntity.getId() != null
                        && item.getServId().longValue() == servEntity.getId().longValue()) {
                    int num = item.getNum();
                    subOrder.setNum(item.getNum());
                    subOrder.setMarkCode(item.getMarketCode());
                    // 计算价格
                    int soAmount = num * servEntity.getAmount();
                    subOrder.setAmount(soAmount);
                    subOrder.setRealAmount(soAmount);

                    orderRealAmount += soAmount;
                    break;
                }
            }
            subServOrderMapper.insert(subOrder);
        }
        // 保存主订单
        order.setAmount(orderRealAmount);
        order.setRealAmount(orderRealAmount);
        order.setPaymentType(1);
        mapper.insert(order);
        // 发送prepare pay消息给paid服务
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String shopDate = now.format(formatter);
        String outTradeNo = shopDate + order.getId();
        String subject = "平台虚拟礼物购买";
        String totalAmount = String.valueOf(order.getRealAmount().doubleValue() / 100);
        String sellerId = ysProperties.getSellerId();
        String sellerName = ysProperties.getSellerName();
        Integer paymentType = 1; // 服务订单
        preparePayProvider.sendPreparePay(subOpenId, outTradeNo, shopDate, subject, totalAmount, sellerId, sellerName, paymentType);
        return order.getId();
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Long payDeposit() {
        if (!SecurityUtils.getSubject().isAuthenticated())
            return null;
        // todo: 保证金金额应该从库里取
        Integer busiType = AccountInfo.getBusiType();
        String depoCode = "depo" + busiType;
        InfoServiceProject serviceProject = infoServiceProjectService.getOne(new QueryWrapper<InfoServiceProject>()
                .eq("ServCode", depoCode));
        Integer amountInt = serviceProject.getAmount();
        String amount = String.valueOf(amountInt.doubleValue() / 100);
        // 服务订单表
        BizServOrder servOrder = new BizServOrder();
        servOrder.setOrderType(1);
        servOrder.setUserId(AccountInfo.getUserId());
        Integer amountNum = (int) (Double.parseDouble(amount) * 100);
        servOrder.setAmount(amountNum);
        servOrder.setRealAmount(amountNum);
        servOrder.setPaymentType(1);
        servOrder.setUseDisc(0);
        servOrder.setOrderStatus(1);
        servOrder.setUpdateVer(0);
        servOrder.setDelFlag(0);
        servOrder.setCreateTime(DateUtil.nowLdt());
        servOrder.setGuid(UUID.randomUUID().toString().substring(0, 32));
        this.save(servOrder);
        // 服务子订单表
        BizSubServOrder subServOrder = new BizSubServOrder();
        subServOrder.setId(idGenerator.nextId());
        subServOrder.setOrderId(servOrder.getId());
            // todo: 保证金服务依据不同厂商分为4种
        subServOrder.setServId(serviceProject.getId());
        subServOrder.setAmount(amountNum);
        subServOrder.setRealAmount(amountNum);
        subServOrder.setNum(1);
        subServOrder.setUseDisc(0);
        Map<String, Object> servSnapShot = new HashMap<>();
        subServOrder.setServSnapshot(servSnapShot);
        subServOrder.setDetailStatus(0);
        subServOrder.setUpdateVer(0);
        subServOrder.setDelFlag(0);
        subServOrder.setCreateTime(DateUtil.nowLdt());
        subServOrder.setOrderStatus(1);
        subServOrderMapper.insert(subServOrder);

        // 保证金缴纳记录表
        BizDepositOperateRecord record = new BizDepositOperateRecord();
        record.setUserId(AccountInfo.getUserId());
        record.setBusiType(AccountInfo.getBusiType());
        record.setBusiId(AccountInfo.getBusiId());
        record.setOptType(1);
        record.setAmount(amountNum);
        record.setCreateTime(DateUtil.nowLdt());
        bizDepositOperateRecordService.save(record);
        // 预支付消息
        String subOpenId = AccountInfo.getOpenId();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String shopDate = DateUtil.nowLd().format(formatter);
        String subject = "河西春平台订单";
        String sellerId = ysProperties.getSellerId();
        String sellerName = ysProperties.getSellerName();
        String outTradeNo = shopDate + servOrder.getId();
        Integer paymentType = 1;
        preparePayProvider.sendPreparePay(subOpenId, outTradeNo, shopDate, subject, amount, sellerId, sellerName, paymentType);
        // 返回虚拟订单Id
        return servOrder.getId();
    }

    @Override
    public Long selfPay() {
        if (!SecurityUtils.getSubject().isAuthenticated())
            return null;
        String amount = "1.0";
        // 服务订单表
        BizServOrder servOrder = new BizServOrder();
        servOrder.setOrderType(4);
        servOrder.setUserId(AccountInfo.getUserId());
        Integer amountNum = (int) (Double.parseDouble(amount) * 100);
        servOrder.setAmount(amountNum);
        servOrder.setRealAmount(amountNum);
        servOrder.setPaymentType(1);
        servOrder.setUseDisc(0);
        servOrder.setOrderStatus(1);
        servOrder.setUpdateVer(0);
        servOrder.setDelFlag(0);
        servOrder.setCreateTime(DateUtil.nowLdt());
        servOrder.setGuid(UUID.randomUUID().toString().substring(0, 32));
        this.save(servOrder);
        // 服务子订单表
        BizSubServOrder subServOrder = new BizSubServOrder();
        subServOrder.setId(idGenerator.nextId());
        subServOrder.setOrderId(servOrder.getId());
        InfoServiceProject serviceProject = infoServiceProjectService.getOne(new QueryWrapper<InfoServiceProject>()
                .eq("ServCode", "validation"));
        subServOrder.setServId(serviceProject.getId());
        subServOrder.setAmount(amountNum);
        subServOrder.setRealAmount(amountNum);
        subServOrder.setNum(1);
        subServOrder.setUseDisc(0);
        Map<String, Object> servSnapShot = new HashMap<>();
        subServOrder.setServSnapshot(servSnapShot);
        subServOrder.setDetailStatus(0);
        subServOrder.setUpdateVer(0);
        subServOrder.setDelFlag(0);
        subServOrder.setCreateTime(DateUtil.nowLdt());
        subServOrder.setOrderStatus(1);
        subServOrderMapper.insert(subServOrder);

        // 预支付消息
        String subOpenId = AccountInfo.getOpenId();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String shopDate = DateUtil.nowLd().format(formatter);
        String subject = "支付验证";
        InfoYsepayRegister register = infoYsepayRegisterService.getOne(new QueryWrapper<InfoYsepayRegister>()
                .eq("BusiId", AccountInfo.getBusiId()));
        String sellerId = register.getUserCode();
        String sellerName = register.getCustName();
        String outTradeNo = shopDate + servOrder.getId();
        Integer paymentType = 1;
        preparePayProvider.sendPreparePay(subOpenId, outTradeNo, shopDate, subject, amount, sellerId, sellerName, paymentType);
        // 返回虚拟订单Id
        return servOrder.getId();
    }

    @Override
    public int selfPaySuccess(Long orderId) {
        BizServOrder servOrder = this.getById(orderId);
        if (servOrder == null || servOrder.getOrderType() != 4)
            return -1;
        infoYsepayRegisterService.update(new UpdateWrapper<InfoYsepayRegister>()
                .eq("UserId", servOrder.getUserId())
                .set("BindWechatBiz", 1));
        return 0;
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public int setServOrderStatus2(Long orderId) {
        boolean done = false;
        BizServOrder servOrder = this.getOne(new QueryWrapper<BizServOrder>().eq("Id", orderId));
        if (servOrder.getOrderStatus() == 1) {
            servOrder.setOrderStatus(2);
            this.updateById(servOrder);
        } else if (servOrder.getOrderStatus() == 2) {
            done = true;
        }

        List<BizSubServOrder> subServOrders = bizSubServOrderService.list(new QueryWrapper<BizSubServOrder>()
                                                                            .eq("OrderId", orderId));
        for (BizSubServOrder subServOrder : subServOrders) {
            if (subServOrder.getOrderStatus() == 1) {
                subServOrder.setOrderStatus(2);
                bizSubServOrderService.updateById(subServOrder);
            }
        }

        if (done)
            return 2;
        else
            return 1;
    }

    @Override
    public List<Map<String, Object>> getServOrdersToDivide(int limit) {
        return mapper.getServOrdersToDivide(limit);
    }
}
